from collections import defaultdict
from typing import Annotated

from fastapi import APIRouter, Depends, Request
from sqlalchemy import select

from utils.export import export_to_csv, save_csv_from_buffer
from db.db import AsyncSession, get_session
from models.models import Schedule, ScheduleName, ApprovedSchedule
from choices.choices import Modality, ExportFormat
from routers.users import oauth2_scheme


schedule_router = APIRouter()


@schedule_router.get("/schedule_name")
async def get_schedule_name(
    token: Annotated[str, Depends(oauth2_scheme)],
    session: AsyncSession = Depends(get_session),
):
    """Возвращает все названия расписания."""
    query_result = await session.execute(select(ScheduleName))
    return query_result.scalars().all()


@schedule_router.get("/doctors_schedule")
async def get_schedule_by_doctors(
    schedule_name: str,
    token: Annotated[str, Depends(oauth2_scheme)],
    doctors_name: str = None,
    ready: bool = None,
    session: AsyncSession = Depends(get_session),
    limit: int = 15,
    offset: int = 0,
):
    """Возвращает все расписания с фильтром по врачам."""
    query = (
        select(
            Schedule,
        )
        .where(
            Schedule.schedule_name == schedule_name,
        ).order_by(
            Schedule.name.asc(),
            Schedule.date.asc(),
        )
        .limit(limit)
        .offset(offset)
    )
    if doctors_name:
        query = query.where(Schedule.name == doctors_name)
    if ready:
        query = query.where(Schedule.ready == ready)
    query_result = await session.execute(query)
    return query_result.scalars().all()


@schedule_router.get("/doctors_schedule_by_modality")
async def get_schedule_by_modality(
    schedule_name: str,
    token: Annotated[str, Depends(oauth2_scheme)],
    modality: Modality = None,
    session: AsyncSession = Depends(get_session)
):
    """Возвращает все расписания с фильтром по модальности."""
    query = (
        select(
            Schedule.name,
            Schedule.modality,
            Schedule.date,
            Schedule.workhours
        )
        .where(
            Schedule.schedule_name == schedule_name,
        )
    )

    if modality:
        query = query.where(Schedule.modality == modality.value)

    query = query.order_by(
        Schedule.name,
        Schedule.modality,
        Schedule.date
    )

    query_result = await session.execute(query)
    result = query_result.fetchall()

    schedule_data = defaultdict(list)

    for row in result:
        name, modality, md, workhours = row
        if name not in schedule_data:
            schedule_data[name].append({"modality": modality, "name": name, "workhours": []})
        schedule_data[name][-1]["workhours"].append({"date": md.strftime('%m.%d'), "hours": workhours})

    final_response = []
    for name, data in schedule_data.items():
        final_response.append({
            "name": data[0]["name"],
            "modality": data[0]["modality"],
            "workhours": data[0]["workhours"]
        })

    dates = set(md.strftime('%m.%d') for _, _, md, _ in result)

    return {"schedule": final_response, "dates": list(dates)}


@schedule_router.get("/export_to")
async def export_to(
    schedule_name: str,
    request: Request,
    token: Annotated[str, Depends(oauth2_scheme)],
    export_format: ExportFormat,
    session: AsyncSession = Depends(get_session),
):
    """Возвращает все расписания с фильтром по модальности."""
    query = (
        select(
            Schedule
        )
        .where(
            Schedule.schedule_name == schedule_name,
        )
    )
    query_result = await session.execute(query)
    schedule_data = query_result.scalars().all()
    bytes_data = export_to_csv(data=schedule_data)
    save_csv_from_buffer(csv_data=bytes_data, file_path=f'download/{schedule_name}.csv')
    file_url = request.url_for('download', path=f'{schedule_name}.csv').components.geturl()
    return {'msg': file_url}


@schedule_router.post("/approved_schedule")
async def create_approved_schedule(
    schedule_name: str,
    token: Annotated[str, Depends(oauth2_scheme)],
    session: AsyncSession = Depends(get_session),
):
    """Создает утвержденное расписание."""
    query = select(ApprovedSchedule)
    query_result = await session.execute(query)
    approved_schedule = query_result.scalars().first()
    if approved_schedule:
        approved_schedule.name = schedule_name
    if not approved_schedule:
        approved_schedule = ApprovedSchedule(name=schedule_name)
        session.add(approved_schedule)
    await session.commit()
    await session.refresh(approved_schedule)
    return approved_schedule


@schedule_router.get("/approved_schedule")
async def get_approved_schedule(
    token: Annotated[str, Depends(oauth2_scheme)],
    session: AsyncSession = Depends(get_session),
):
    """Вовзращает название утвержденного расписания."""
    query = select(ApprovedSchedule)
    query_result = await session.execute(query)
    return query_result.scalars().first()
